#!/bin/bash
#=================================================================================================
#TODO: insert the valid regexp for the protocol
#TODO: check with Leon whether is protocls are correct, for example SMTP output regexp

# NOTE: no whitespaces when declaring variables!!

# protocols INPUT regexp:
#TODO: check why HTTP_REGEXP_IN and POP_REGEXP_IN makes problems in iptables...
#TODO check BAD REGEXPS: HTTP_REGEXP_IN, POP_REGEXP_IN, SSL_REGEXP_OUT


HTTP_REGEXP_IN="http/(0\.9|1\.0|1\.1) [1-5][0-9][0-9] [\x09-\x0d -~]*(connection:|content-type:|content-length:|date:)|post [\x09-\x0d -~]* http/[01]\.[019]"

FTP_REGEXP_IN="^220[\x09-\x0d -~]*ftp"
TELNET_REGEXP_IN="^\xff[\xfb-\xfe].\xff[\xfb-\xfe].\xff[\xfb-\xfe]"

#POP_REGEXP_IN="^(\+ok|-err)"
POP_REGEXP_IN="^(\+ok [\x09-\x0d -~]*(ready|hello|pop|starting)|-err [\x09-\x0d -~]*(invalid|unknown|unimplemented|unrecognized|command))"
#POP_REGEXP_IN=|^(\+ok .*pop)"

SSH_REGEXP_IN="^ssh-[12]\.[0-9]"

# protocols OUTPUT regexp: 
HTTP_REGEXP_OUT="get .* http/[01]\.[019]"
FTP_REGEXP_OUT="^230 User .* logged in\."
TELNET_REGEXP_OUT="^\xff[\xfb-\xfe].\xff[\xfb-\xfe].\xff[\xfb-\xfe]"
SSH_REGEXP_OUT="^ssh-[12]\.[0-9]"
SSL_REGEXP_OUT="^(.?.?\x16\x03.*\x16\x03|.?.?\x01\x03\x01?.*\x0b)"
SMTP_REGEXP_OUT="EHLO" 

# This computer IP
curIP=`ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`
#=================================================================================================
init_iptables()
{
	# Initialization (ACCEPT all)
	iptables -t mangle -P INPUT ACCEPT
	iptables -t mangle -P OUTPUT ACCEPT
	iptables -t mangle -F INPUT
	iptables -t mangle -F OUTPUT
}

load_product()
{
	echo 'Loading the product:'
	echo 'insmod ipt_ipcontext.ko'
	rmmod -f ipt_ipcontext
	insmod ipt_ipcontext.ko
	init_iptables
}

unload_product()
{
	echo 'Unloading the product:'
	echo 'rmmod ipt_ipcontext'
	rmmod -f ipt_ipcontext
}	

block_port_OUTPUT()
{
	iptables -t mangle -A OUTPUT -p tcp --dport $1 -j DROP
}

HTTP_INPUT_ALLOW() 
{
	iptables -t mangle -A INPUT -j DROP -m ipcontext --ipcontext_port 80 --ipcontext_protocol http --ipcontext_regexp $HTTP_REGEXP_IN --ipcontext_log --ipcontext_dir 1
}

HTTP_INPUT_DENY() 
{
	iptables -t mangle -A INPUT -j DROP -m ipcontext --ipcontext_port 80 --ipcontext_protocol http --ipcontext_regexp "blablabla" --ipcontext_log --ipcontext_dir 1
}

HTTP_OUTPUT_ALLOW() 
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 80 --ipcontext_protocol http --ipcontext_regexp $HTTP_REGEXP_OUT --ipcontext_log
}

HTTP_OUTPUT_DENY() 
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 80 --ipcontext_protocol http --ipcontext_regexp "blablabla" --ipcontext_log
}

SMTP_OUTPUT_ALLOW() 
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 25 --ipcontext_protocol smtp --ipcontext_regexp $SMTP_REGEXP_OUT --ipcontext_log
}

SMTP_OUTPUT_DENY() 
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 25 --ipcontext_protocol smtp --ipcontext_regexp "blablabla" --ipcontext_log
}	

POP_INPUT_ALLOW() 
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 995 --ipcontext_protocol pop --ipcontext_regexp $POP_REGEXP_IN --ipcontext_log --ipcontext_dir 1
}

POP_INPUT_DENY() 
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 995 --ipcontext_protocol pop --ipcontext_regexp "blablabla" --ipcontext_log --ipcontext_dir 1 
}

TELNET_INPUT_ALLOW()
{
	iptables -t mangle -A INPUT -j DROP -m ipcontext --ipcontext_port 23 --ipcontext_protocol telnet --ipcontext_regexp $TELNET_REGEXP_IN --ipcontext_log --ipcontext_dir 1
}

TELNET_INPUT_DENY()
{
	iptables -t mangle -A INPUT -j DROP -m ipcontext --ipcontext_port 23 --ipcontext_protocol telnet --ipcontext_regexp "blablabla" --ipcontext_log --ipcontext_dir 1
}

TELNET_OUTPUT_ALLOW()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 23 --ipcontext_protocol telnet --ipcontext_regexp $TELNET_REGEXP_OUT --ipcontext_log
}

TELNET_OUTPUT_DENY()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 23 --ipcontext_protocol telnet --ipcontext_regexp "blablabla" --ipcontext_log
}


SSH_INPUT_ALLOW()
{
	iptables -t mangle -A INPUT -j DROP -m ipcontext --ipcontext_port 22 --ipcontext_protocol ssh --ipcontext_regexp $SSH_REGEXP_IN --ipcontext_dir 1 --ipcontext_log
}

SSH_INPUT_DENY()
{
	iptables -t mangle -A INPUT -j DROP -m ipcontext --ipcontext_port 22 --ipcontext_protocol ssh --ipcontext_regexp "blablabla" --ipcontext_dir 1 --ipcontext_log
}

SSH_OUTPUT_ALLOW()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 22 --ipcontext_protocol ssh --ipcontext_regexp $SSH_REGEXP_OUT --ipcontext_log
}

SSH_OUTPUT_DENY()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 22 --ipcontext_protocol ssh --ipcontext_regexp "blablabla" --ipcontext_log
}

SSL_OUTPUT_ALLOW()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 443 --ipcontext_protocol ssl --ipcontext_regexp $SSL_REGEXP_OUT --ipcontext_log
}

SSL_OUTPUT_DENY()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 443 --ipcontext_protocol ssl --ipcontext_regexp "blablabla" --ipcontext_log
}

FTP_OUTPUT_ALLOW()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 21 --ipcontext_protocol ftp --ipcontext_regexp $FTP_REGEXP_OUT --ipcontext_log
}

FTP_OUTPUT_ALLOW()
{
	iptables -t mangle -A OUTPUT -j DROP -m ipcontext --ipcontext_port 21 --ipcontext_protocol ftp --ipcontext_regexp "blablabla" --ipcontext_log
}

#=================================================================================================
clear

#TODO: remove this comment
####################init_iptables
echo 'Firewall Project Acceptance Tests Menu:'
echo '======================================'
echo 'For selecing an accpetance-test for a client-story press any number between 1-5:'
echo 'for other options press any number between 6-10'
echo '1) The product is a firewall'
echo '2) The product has an interface'
echo '3) The firewall is able to check the validity of the protocol'
echo '4) The product has a logger'
echo '5) The product doesnt consume significant system-resources'
echo '6) press 6 for flushing all iptables rules'
echo '7) press 7 for sending an e-mail'
echo '8) press 8 for sending a message to remote computer via HTTP protocol using netcat'
echo '9) press 9 for sending a message to remote computer via TELNET protocol using netcat'
echo '10) press 11 for viewing the iptables rules'

read option

if [ $option = '1' ]
then
	clear
	echo 'In this acceptance-test you will be able to check basic properties of the firewall:'
	echo '=================================================================================='
	echo '1) Blocking outgoing port'
	echo '2) Blocking IP'
	echo '3) Blocking TCP protocol'
	read option	
	if [ $option = '1' ]
	then
		clear
		block_port_OUTPUT 23
		echo 'This acceptance test will block port 23 (out direction)'
		echo 'We will try telnet to t2.technion.ac.il and will not succeed'
		echo 'press any key to continue...'
		read chT
		echo 'telnet t2.technion.ac.il'
		telnet t2.technion.ac.il
	elif [ $option = '2' ]
	then
		clear
		echo 'This acceptance test will block surfing to www.technion.ac.il'
		echo 'press any key to continue...'
		read ch
		iptables -t mangle -A OUTPUT -d www.technion.ac.il -j DROP
		firefox --display :0 www.technion.ac.il
		firefox --display :0 www.walla.co.il
	elif [ $option = '3' ]
	then
		clear
		init_iptables
		echo 'This acceptance test will block tcp protocol (out direction)'
		iptables -t mangle -A OUTPUT -p tcp -j DROP
		firefox --display :0 www.walla.co.il
		firefox --display :0 www.one.co.il
	else
		echo 'invalid input'
		exit 1
	fi
elif [ $option = '2' ]
then
	clear
	echo 'In this acceptance test we will use the product via a GUI'
	echo 'press any key to continue...'
	read ch
	#TODO: specify the type of GUI (advanced or simple user)
	rmmod -f ipt_ipcontext
	./firewall
elif [ $option = '3' ]
then
	clear
	init_iptables
	echo 'In this acceptance test we will examine the protocols our product supports'	
	echo 'please choose a protocol'
	echo '1) HTTP'
	echo '2) FTP'
	echo '3) POP'
	echo '4) SMTP'
	echo '5) SSL'
	echo '6) TELNET'
	echo '7) SSH'

	read option

	if [ $option = '1' ] #HTTP
	then
		clear 
		echo 'please select the direction of examining the protocol'
		echo '1) INPUT'
		echo '2) OUTPUT'
		read direction
		if [ $direction = '1' ] #INPUT
		then
			clear
			echo 'In this acceptance test we will examine the HTTP protocol in INPUT direction'
			echo 'we will show a little client-server interaction.'
			echo 'This computer will be used as a server.'
			echo 'it will use netcat for opening port 80'
			echo 'choose option:'
			echo '1) HTTP INPUT: ALLOW'
			echo '2) HTTP INPUT: DENY'
			read option

			if [ $option = '1' ] #allow
			then
				clear
				echo "After this computer opens port 80, the client will have to type this via his computer: nc" $curIP 80 $HTTP_REGEXP_INPUT
				echo 'press any key to continue...'
				read ch
				load_product
				echo 'adding the desired rule...'
				HTTP_INPUT_ALLOW
			elif [ $option = '2' ] #deny
			then
				clear
				echo "After this computer opens port 80, the client will have to type this via his computer: nc" $curIP 80 "REGEXP"
				echo 'press any key to continue...'
				read ch
				load_product
				echo 'adding the desired rule...'
				HTTP_INPUT_DENY
			else
				echo 'invalid input'
				exit 1
			fi
			echo 'opening port 80 on this computer using netcat:'
			echo 'nc -l -p 80'
			echo 'listening on port 80...'
			nc -l -p 80
		elif [ $direction = '2' ] #OUTPUT
		then
			clear
			echo 'In this acceptance test we will examine the HTTP protocol in OUTPUT direction'
			echo 'we will try surfing the web'
			echo 'choose option:'
			echo '1) HTTP OUTPUT: ALLOW'
			echo '2) HTTP OUTPUT: DENY'
			read option
			clear
			if [ $option = '1' ] #allow
			then
				echo 'we will allow using HTTP protocol via port 80 on OUTPUT direction'
				load_product
				echo 'press any key for adding the appropiate rule...'
				read ch
				HTTP_OUTPUT_ALLOW
				firefox --display :0 www.walla.co.il
			elif [ $option = '2' ] #deny
			then
				echo 'we will deny using HTTP protocol via port 80 on OUTPUT direction'
				load_product
				echo 'press any key for adding the appropiate rule...'
				read ch
				HTTP_OUTPUT_DENY
				firefox --display :0 www.walla.co.il
			else
				echo 'invalid input'
			fi
		else
			echo 'invalid input'
			exit 1
		fi
	elif [ $option = '2' ] #FTP
	then
		echo 'third iteration?'
	elif [ $option = '3' ] #POP
	then
		clear 
		echo 'In this acceptance test we will recieve mail using the thunderbird software'
		echo 'You have the option to decide if the mail will be recieved or not'
		echo 'choose option:'
		echo '1) Allow recieving the e-mail'
		echo '2) Deny recieving the e-mail'
		read option

		clear
		echo 'press any key to load the product...'
		load_product
		echo 'press any key for adding the appropiate rule...'
		read ch

		if [ $option = '1' ] #allow
		then		
			POP_INPUT_ALLOW	
			iptables -t mangle -L
		elif [ $option = '2' ] #deny
		then	
			POP_INPUT_DENY
			iptables -t mangle -L
		else	
			echo 'invalid input'
			exit 1
		fi	
		echo 'please open up manually thunderbird'
	elif [ $option = '4' ] #SMTP
	then
		clear 
		echo 'In this acceptance test we will send mail to some mail using the evolution software'
		echo 'You have the option to decide if the mail will be sent or not'
		echo 'choose option:'
		echo '1) Allow sending the e-mail'
		echo '2) Deny sending the e-mail'
		read option

		clear
		echo 'press any key to load the product...'
		load_product
		echo 'press any key for adding the appropiate rule...'
		read ch

		if [ $option = '1' ] #allow
		then		
			SMTP_OUTPUT_ALLOW	
		elif [ $option = '2' ] #deny
		then	
			SMTP_OUTPUT_DENY
		else	
			echo 'invalid input'
			exit 1
		fi	
		evolution --display :0
	elif [ $option = '5' ] #SSL
	then
		clear
		echo 'In this acceptance test we will examine the SSL protocol in OUTPUT direction'
		echo 'choose option:'
		echo '1) SSL OUTPUT: ALLOW'
		echo '2) SSL OUTPUT: DENY'
		read option
		
		if [ $option = '1' ] #ALLOW
		then
			clear
			echo 'we will allow using SSL protocol via port 443 on OUTPUT direction'
			load_product
			echo 'press any key for adding the appropiate rule...'
			read ch
			SSL_OUTPUT_ALLOW	
		elif [ $option = '2' ] #DENY	
		then
			clear
			echo 'we will deny using SSL protocol via port 443 on OUTPUT direction'
			load_product
			echo 'press any key for adding the appropiate rule...'
			read ch
			SSL_OUTPUT_DENY
		else
			echo 'invalid input'	
			exit 1	
		fi
		firefox --display :0 https://www.gmail.com	
	elif [ $option = '6' ] #TELNET
	then
		clear 
		echo 'please select the direction of examining the protocol'
		echo '1) INPUT'
		echo '2) OUTPUT'
		read direction
		if [ $direction = '1' ] #INPUT	
		then
			clear
			echo 'In this acceptance test we will examine the TELNET protocol in INPUT direction'
			echo 'we will show a little client-server interaction.'
			echo 'This computer will be used as a server.'
			echo 'it will use netcat for opening port 23'
			echo 'choose option:'
			echo '1) TELNET INPUT: ALLOW'
			echo '2) TELNET INPUT: DENY'
			read option

			if [ $option = '1' ] #allow
			then
				clear
				echo "After this computer opens port 23, the client will have to type this via his computer: telnet" $curIP 23 $TELNET_REGEXP_IN
				echo 'press any key to continue...'
				read ch
				load_product
				echo 'adding the desired rule...'
				TELNET_INPUT_ALLOW
			elif [ $option = '2' ] #deny
			then
				clear
				echo "After this computer opens port 23, the client will have to type this via his computer: telnet" $curIP 23 $TELNET_REGEXP_IN
				echo 'press any key to continue...'
				read ch
				load_product
				echo 'adding the desired rule...'
				TELNET_INPUT_DENY
			else
				echo 'invalid input'	
				exit 1		
			fi

			echo 'opening port 23 on this computer using netcat:'
			echo 'nc -l -p 23'
			echo 'listening on port 23...'
			nc -l -p 23
		elif [ $direction = '2' ] #OUTPUT
		then
			clear
			echo 'In this acceptance test we will examine the TELNET protocol in OUTPUT direction'
			echo 'we will try telneting to t2.technion.ac.il'
			echo 'choose option:'
			echo '1) TELNET OUTPUT: ALLOW'
			echo '2) TELNET OUTPUT: DENY'
			read option
			clear
			if [ $option = '1' ] #allow
			then
				echo 'we will allow using TELNET protocol via port 23 on OUTPUT direction'
				load_product
				echo 'press any key for adding the appropiate rule...'
				read ch
				TELNET_OUTPUT_ALLOW	
				telnet t2.technion.ac.il
			elif [ $option = '2' ] #deny
			then
				echo 'we will deny using TELNET protocol via port 23 on OUTPUT direction'
				load_product
				echo 'press any key for adding the appropiate rule...'
				read ch
				TELNET_OUTPUT_DENY
				telnet t2.technion.ac.il
			else
				echo 'invalid input'
				exit 1
			fi
			
		else
			echo 'invalid input'
			exit 1
		fi	
	elif [ $option = '7' ] #SSH
	then
		clear 
		echo 'please select the direction of examining the protocol'
		echo '1) INPUT'
		echo '2) OUTPUT'
		read direction
		if [ $direction = '1' ] #INPUT
		then
			clear
			echo 'In this acceptance test we will examine the SSH protocol in INPUT direction'
			echo 'we will show a little client-server interaction.'
			echo 'This computer will be used as a server.'
			echo 'it will use netcat for opening port 22'
			echo 'choose option:'
			echo '1) SSH INPUT: ALLOW'
			echo '2) SSH INPUT: DENY'
			read option

			if [ $option = '1' ] #allow
			then
				clear
				echo 'For allowing protocol SSH INPUT direction'
				echo 'will do ssh to t2.technion.ac.il, which is output direction'
				echo 'but then we will get response from the t2 server, and that is'
				echo 'how we will check SSH in INPUT direction'
				echo 'press any key to continue...'
				read ch
				load_product
				echo 'adding the desired rule...'
				SSH_INPUT_ALLOW
			elif [ $option = '2' ] #deny
			then
				clear
				echo 'For denying protocol SSH OUTPUT direction'
				echo 'will do ssh to t2.technion.ac.il, which is output direction'
				echo 'but then we will get response from the t2 server, and that is'
				echo 'how we will check SSH in OUTPUT direction'
				echo 'press any key to continue...'
				read ch
				load_product
				echo 'adding the desired rule...'
				SSH_INPUT_DENY
			else
				echo 'invalid input'
				exit 1
			fi	
			ssh t2.technion.ac.il
		elif [ $direction = '2' ] #OUTPUT
		then
			clear
			echo 'In this acceptance test we will examine the SSH protocol in OUTPUT direction'
			echo 'choose option:'
			echo '1) SSH OUTPUT: ALLOW'
			echo '2) SSH OUTPUT: DENY'
			read option
			clear
			if [ $option = '1' ] #allow
			then
				echo 'we will allow using SSH protocol via port 22 on OUTPUT direction'
				load_product
				echo 'press any key for adding the appropiate rule...'
				read ch
				SSH_OUTPUT_ALLOW
			elif [ $option = '2' ] #deny
			then
				echo 'we will deny using SSH protocol via port 22 on OUTPUT direction'
				load_product
				echo 'press any key for adding the appropiate rule...'
				read ch
				SSH_OUTPUT_DENY
			else
				echo 'invalid input'
				exit 1
			fi
		else
			echo 'invalid input'
			exit 1
		fi
		ssh t2.technion.ac.il	
	else
 		echo 'invalid input'
 		exit 1
	fi
elif [ $option = '4' ]
then
	clear
	echo 'In this acceptance test we will use the logger of our product'
	echo 'we will load our product, add a rule that blocks protocol http (out direction)'
	echo 'then we will try surf the web, we will not success and we will'
	echo 'see that the logger denied the session'
	echo 'press any key to load the product...'
	read ch
	load_product
	echo 'enter the filename the logger will save its logging to: (in this directory)'
	read filename
	./log_parser $filename
	echo 'The log file context before adding the rule:'
	cat $filename
	echo 'press any key to continue...'
	read ch
	echo 'adding a rule for blocking http (out direction)'
	HTTP_OUTPUT_DENY
	firefox --display :0 www.technion.co.il
	echo 'press any key to show the context of the log file:'
	read ch
	./log_parser $filename
	cat $filename
elif [ $option = '5' ]
then
	clear
	echo 'In this acceptance test we will download a big file using the ftp protocol'
	echo 'and compare system-resources usage when the product is ON and OFF'
	echo 'please choose the mode you want to download the file:'
	echo '1) Product is ON'
	echo '2) Product is OFF'
	echo '3) Download the file two times: when the product is ON and after that when the'
	echo 'then product is OFF'
	read option
	clear

	if [ $option = '1' ] #ON
	then
		load_product
		echo
		echo 'press any key to download the file when the product is ON...'
		read ch
		ncftpget ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5.0.7/source/firefox-1.5.0.7-source.tar.bz2
	elif [ $option = '2' ] #OFF
	then
		unload_product
		echo
		echo 'press any key to download the file when the product is OFF...'
		read ch
		ncftpget ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5.0.7/source/firefox-1.5.0.7-source.tar.bz2
	elif [ $option = '3' ] #ALL
	then
		load_product
		echo
		echo 'Starting to download the file...'
		ncftpget ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5.0.7/source/firefox-1.5.0.7-source.tar.bz2
		echo
		unload_product
		echo
		echo 'Starting to download the file...'
		ncftpget ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5.0.7/source/firefox-1.5.0.7-source.tar.bz2
	else 
		echo 'invalid input'
		exit 1	
	fi
elif [ $option = '6' ]
then
	init_iptables
	clear
	iptables -t mangle -L
elif [ $option = '7' ]
then
	echo "you can send e-mail via the evolution program"
	echo "for sending e-mail press any key..."
	read ch
	evolution --display :0
elif [ $option = '8' ] #HTTP
then
	clear
	echo 'This acceptance test will send a message to a remote computer'
	echo 'via the HTTP protocol(using port 80)'
	echo 'Assumption: the remote computer (the server) is listening on port 80'
	echo 'Enter the message you want to be sent:'
	read msg
	rm -f msgHTTPFile
	echo $HTTP_REGEXP_IN  $msg > msgHTTPFile
	echo 'Enter the remote computer IP:'
	read compIP
	echo 'press any key to send the message using netcat...'
	read ch
	clear
	nc $compIP 80 < msgHTTPFile
elif [ $option = '9' ] #TELNET 
then
	clear
	echo 'This acceptance test will send a message to a remote computer'
	echo 'via the TELNET protocol (using port 23)'
	echo 'Assumption: the remote computer (the server) is listening on port 23'
	echo 'Enter the message you want to be sent:'
	read msg
	rm -f msgTELNETFile
	echo $TELNET_REGEXP_IN $msg > msgTELNETFile
	echo 'Enter the remote computer IP:'
	read compIP
	echo 'press any key to send the message using telnet...'
	read ch
	clear
	telnet $compIP < msgTELNETFile
elif [ $option = '10' ]
then
	clear
	iptables -t mangle -L
else
	echo 'ivalid input'
fi
